#ifndef QMC5883P_H
#define QMC5883P_H

#ifdef __cplusplus
extern "C"
{
#endif
    /*---------------------------- C Scope ---------------------------*/
#include "stdint.h"
	#include "math.h"

#define CHIP_ID 0x00
#define X_L_OUT 0x01
#define X_H_OUT 0x02
#define Y_L_OUT 0x03
#define Y_H_OUT 0x04
#define Z_L_OUT 0X05
#define Z_H_OUT 0x06
#define STATUS  0X09
#define MODE_REG 0X0A
#define SELT_TEST_REG 0X0B
#define DEFINE_REG 0x29

#ifdef __cplusplus
}

typedef enum 
{
    Suspend=0,
    Normal=1,
    Single=2,
    Continuous=3,
}Mode_t;

typedef struct 

{
    /* data */
    float mx;
    float my;
    float mz;
    int16_t mx_raw;
    int16_t my_raw;
    int16_t mz_raw; 
}Q_RawData_t;

typedef enum{
    R30G = 0,
    R12G=1,
    R8G=2,
    R2G=3,
}Range_t;

typedef enum{
    ODR_10= 0,
    ODR_50=1,
    ODR_100=2,
    ODR_200=3,
}ODR_t;

typedef enum
{
    OSR_8=0,
    OSR_4=1,
    OSR_2=2,
    OSR_1=3,
}Filter_t;

typedef enum
{
    OSR_2_1=0,
    OSR_2_2=1,
    OSR_2_4=2,
    OSR_2_8=3,
}Filter_Depth_t;

typedef enum
{
    SET_RESET_ON=0,
    SET_ONLY_ON=1,
    SET_RESET_OFF=2
}SetRestMode_t;

class QMC5883P
{
private:
    Mode_t mode;
    const uint16_t ADDR = 0x2C;
    float delta_xyz[3];

    Range_t Gain;
    ODR_t odr;
    Filter_t filter;
    Filter_Depth_t depth;
    SetRestMode_t setMode;

    float factor[3]={1.0f,1.0f,1.0f}; // xyz

    //control reg
    uint8_t SetMode();
    uint8_t SetODR();
    uint8_t SetFilter();
    uint8_t SetDepth();

    //control reg 2
    uint8_t SoftReset(uint8_t _flag){return (_flag > 0) ? 1:0;}
    uint8_t SetSelfTest(uint8_t _flag){return (_flag > 0) ? 1:0;}
    uint8_t SetGain();
    uint8_t SetSetRestMode();

    uint16_t getSensitivity();

public:
    Q_RawData_t rawData_t;
    QMC5883P(Mode_t _mode,Range_t _gain = R30G,ODR_t _odr=ODR_200,Filter_t _filter=OSR_8,
             Filter_Depth_t _depth=OSR_2_8,SetRestMode_t _setmode = SET_RESET_OFF):
                mode(_mode),Gain(_gain),odr(_odr),filter(_filter),depth(_depth),setMode(_setmode)
                {

                };
    virtual unsigned char i2c_write(unsigned char slave_addr,
                                    unsigned char reg_addr,
                                    unsigned short len,
                                    unsigned char *data_ptr) = 0;
    virtual unsigned char i2c_read(unsigned char Address,
                                   unsigned char RegisterAddr,
                                   unsigned int RegisterLen,
                                   unsigned char *RegisterValue) = 0;
    virtual void delay_ms(uint32_t _ms) = 0;
    void SetUp();
    void SelfTest();
    void SoftReset();
    void GetMeasureMentData();
    uint8_t TestConnection();

    uint8_t getControlReg();
    uint8_t getControlReg2();
};

/*---------------------------- C++ Scope ---------------------------*/

#endif

#endif
